package com.jeeplus.modules.work.utils;

import com.jeeplus.common.utils.CacheUtils;
import net.sf.json.JSONException;
import net.sf.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.security.DigestException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.*;

@Component
public class WeixinUtil {
    private static Logger log = LoggerFactory.getLogger(WeixinUtil.class);
    private static final String validChars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
    public static final String TOKEN_CACHE = "tokenCache";
    //微信AppID
    @Value("${AppID}")
    private String AppID;
    //微信AppSecret
    @Value("${AppSecret}")
    private String AppSecret;
    //获取access_token
    public void getAccessToken() {
        String requestUrl = WeiXinConfig.access_token_url.replace("APPID", AppID).replace("APPSECRET", AppSecret);
        requestUrl = requestUrl.replace("api.weixin.qq.com", "tfzw.tfgyc.com");
        JSONObject jsonObject = JSONObject.fromObject(HttpRequestUtil.sendPost(requestUrl,null));
        // 如果请求成功
        if (null != jsonObject) {
            try {
                log.error("--------------获取----token--------"+String.valueOf(jsonObject.getString("access_token")));
                CacheUtils.put(TOKEN_CACHE, "token", String.valueOf(jsonObject.getString("access_token")));
                getJsapiTicket(CacheUtils.get(TOKEN_CACHE,"token").toString());
            } catch (JSONException e) {
                e.printStackTrace();
            }
        }
    }
    /**
     * 获取 JsapiTicket
     * azj
     * @param accessToken
     * @return
     */
    public JsapiTicket getJsapiTicket(String accessToken) {
        JsapiTicket jsapiTicket = null;
        String url = WeiXinConfig.jsapi_ticket_url.replace("ACCESS_TOKEN", accessToken);
        JSONObject jsonObject = JSONObject.fromObject(HttpRequestUtil.sendPost(url,null));
        // 如果请求成功
        if (null != jsonObject) {
            try {
                jsapiTicket = new JsapiTicket();
                jsapiTicket.setErrcode(jsonObject.getString("errcode"));
                jsapiTicket.setErrmsg(jsonObject.getString("errmsg"));
                jsapiTicket.setTicket(jsonObject.getString("ticket"));
                jsapiTicket.setExpiresIn(jsonObject.getString("expires_in"));
                WeiXinConfig.jsapiTicket = jsapiTicket;
            } catch (JSONException e) {
                jsapiTicket = null;
                e.printStackTrace();
            }
        }
        return jsapiTicket;
    }


    /**
     * 获取网页配置信息
     *
     * @param url
     * @return
     * @throws Exception
     */
    public  WebConfigInfo getWebConfigInfo(String url,String AppID){

        WebConfigInfo webConfigInfo = new WebConfigInfo();
        String noncestr = generateRandomString(16);
        String jsapi_ticket = WeiXinConfig.jsapiTicket.getTicket();
        String timestamp = System.currentTimeMillis() / 1000 + "";
        Map<String, Object> paraMap = new TreeMap<String, Object>();
        paraMap.put("noncestr", noncestr);
        paraMap.put("jsapi_ticket", jsapi_ticket);
        paraMap.put("timestamp", timestamp);
        paraMap.put("url", url);
        try{
            String sha1String = SHA1(paraMap);
            webConfigInfo.setNonceStr(noncestr);
            webConfigInfo.setTimestamp(timestamp);
            webConfigInfo.setSignature(sha1String);
            webConfigInfo.setAppId(AppID);
            return webConfigInfo;
        }catch (Exception e){
            log.error("获取微信配置失败！");
        }
        return null;
    }
    // **************************************

    public  String SHA1(Map<String, Object> maps) throws DigestException {
        // 获取信息摘要 - 参数字典排序后字符串
        String decrypt = getOrderByLexicographic(maps);
        try {
            // 指定sha1算法
            MessageDigest digest = MessageDigest.getInstance("SHA-1");
            digest.update(decrypt.getBytes());
            // 获取字节数组
            byte messageDigest[] = digest.digest();
            // Create Hex String
            StringBuffer hexString = new StringBuffer();
            // 字节数组转换为 十六进制 数
            for (int i = 0; i < messageDigest.length; i++) {
                String shaHex = Integer.toHexString(messageDigest[i] & 0xFF);
                if (shaHex.length() < 2) {
                    hexString.append(0);
                }
                hexString.append(shaHex);
            }
            return hexString.toString();

        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
            throw new DigestException("签名错误！");
        }
    }

    private  String getOrderByLexicographic(Map<String, Object> maps) {
        log.info(splitParams(lexicographicOrder(getParamsName(maps)), maps));
        System.out.println(splitParams(lexicographicOrder(getParamsName(maps)), maps));
        return splitParams(lexicographicOrder(getParamsName(maps)), maps);
    }

    /**
     * 获取参数名称 key
     *
     * @param maps 参数key-value map集合
     * @return
     */
    private  List<String> getParamsName(Map<String, Object> maps) {
        List<String> paramNames = new ArrayList<String>();
        for (Map.Entry<String, Object> entry : maps.entrySet()) {
            paramNames.add(entry.getKey());
        }
        return paramNames;
    }

    /**
     * 参数名称按字典排序
     *
     * @param paramNames 参数名称List集合
     * @return 排序后的参数名称List集合
     */
    private  List<String> lexicographicOrder(List<String> paramNames) {
        Collections.sort(paramNames);
        return paramNames;
    }

    /**
     * 拼接排序好的参数名称和参数值
     *
     * @param paramNames 排序后的参数名称集合
     * @param maps       参数key-value map集合
     * @return String 拼接后的字符串
     */
    private  String splitParams(List<String> paramNames, Map<String, Object> maps) {
        StringBuilder paramStr = new StringBuilder();
        for (String paramName : paramNames) {
            paramStr.append(paramName);
            for (Map.Entry<String, Object> entry : maps.entrySet()) {
                if (paramName.equals(entry.getKey())) {
                    paramStr.append("=" + String.valueOf(entry.getValue()) + "&");
                }
            }
        }
        paramStr.deleteCharAt(paramStr.length() - 1);
        return paramStr.toString();
    }

    /**
     * 参数随机的字符串，包括字母和大写的数字
     *
     * @param length
     * @return
     */
    public  String generateRandomString(int length) {
        StringBuffer sb = new StringBuffer();
        Random random = new Random();
        for (int i = 0; i < length; i++) {
            sb.append(validChars.charAt(random.nextInt(validChars.length())));
        }
        return sb.toString();
    }
}

